#ifdef ENABLE_ARM32
    .text
    .align 5
    .global MatmulFloatNeon32OptRemain
#ifndef __APPLE__
    .type MatmulFloatNeon32OptRemain, %function
#endif

// void MatmulFloatNeon32OptRemain(const float *a, const float *b, float *c, int depth, int row, int col, int stride)
// r0: a
// r1: b
// r2: c
// r3: depth
// r4: row
// r5: col
// r6: stride

MatmulFloatNeon32OptRemain:
    // r4-r8 and q4-q7 must be saved according to https://static.docs.arm.com/ihi0042/i/aapcs32.pdf
    push {r4-r8, r10, r11, lr}
    add sp, sp, #32

    ldr r5, [sp, #4]
    ldr r6, [sp, #8]

    mov lr, #32 // sizeof(float) * 8
    mul r12, r3, lr // block stride of lhs/rhs: sizeof(float) * 8 * depth
    mov lr, #4
    mul r11, r5, r6 // stride * col * sizeof(float)
    mul r11, r11, lr
    mov lr, #32
    mul r10, r6, lr // stride * 8 * sizeof(float)

LoopCol:
    mov r6, r0 // reload lhs ptr
    mov r8, r2 // reload dst ptr

    ldr lr, [sp]
    cmp lr, #3
    beq LoopRow3
    cmp lr, #2
    beq LoopRow2
    b LoopRow

    LoopRow3:
        mov r7, r1 // reload rhs ptr
        mov r4, r3 // reload depth
        veor q8, q8, q8
        veor q9, q9, q9
        veor q10, q10, q10
        veor q11, q11, q11
        veor q12, q12, q12
        veor q13, q13, q13

        LoopDepth3:
            vld1.32 {q0}, [r6]!
            vld1.32 {q1, q2}, [r7]!
            vmla.f32 q8, q1, d0[0]
            vmla.f32 q9, q2, d0[0]
            vmla.f32 q10, q1, d0[1]
            vmla.f32 q11, q2, d0[1]
            vmla.f32 q12, q1, d1[0]
            vmla.f32 q13, q2, d1[0]

            subs r4, r4, #1
            bne LoopDepth3

            vst1.32 {q8, q9}, [r8]
            add r8, r8, r11
            vst1.32 {q10, q11}, [r8]
            add r8, r8, r11
            vst1.32 {q12, q13}, [r8]
            add r8, r8, r11

            b LoopRowEnd

    LoopRow2:
        mov r7, r1 // reload rhs ptr
        mov r4, r3 // reload depth
        veor q8, q8, q8
        veor q9, q9, q9
        veor q10, q10, q10
        veor q11, q11, q11

        LoopDepth2:
            vld1.32 {q0}, [r6]!
            vld1.32 {q1, q2}, [r7]!
            vmla.f32 q8, q1, d0[0]
            vmla.f32 q9, q2, d0[0]
            vmla.f32 q10, q1, d0[1]
            vmla.f32 q11, q2, d0[1]

            subs r4, r4, #1
            bne LoopDepth2

            vst1.32 {q8, q9}, [r8]
            add r8, r8, r11
            vst1.32 {q10, q11}, [r8]
            add r8, r8, r11

            b LoopRowEnd

    LoopRow:
        mov r7, r1 // reload rhs ptr
        mov r4, r3 // reload depth
        veor q8, q8, q8
        veor q9, q9, q9

        LoopDepth:
            vld1.32 {q0}, [r6]!
            vld1.32 {q1, q2}, [r7]!
            vmla.f32 q8, q1, d0[0]
            vmla.f32 q9, q2, d0[0]

            subs r4, r4, #1
            bne LoopDepth

            vst1.32 {q8, q9}, [r8]
            add r8, r8, r11

    LoopRowEnd:
        add r1, r1, r12 // rhs ptr + stride
        add r2, r2, r10
        cmp r5, #8
        ble LoopColEnd
        sub r5, r5, #8 // rhs col - 8
        b LoopCol

LoopColEnd:
    sub sp, sp, #32
    pop {r4-r8, r10, r11, pc}
#endif
